package main

import (
	"fmt"
	"google.golang.org/grpc"
	"grpc-stream/proto"
	"net"
	"sync"
	"time"
)

func main() {
	// 创建一个监听tcp，50052端口
	lis, err := net.Listen("tcp", ":50052")
	if err != nil {
		panic(err)
	}
	// new一个grpc的server
	grpcServer := grpc.NewServer()
	// 注册服务
	proto.RegisterGreeterServer(grpcServer, &GreeterServer{})
	// 让grpc对外提供服务
	err = grpcServer.Serve(lis)
	if err != nil {
		panic(err)
	}
}

type GreeterServer struct {
}

// 服务端流模式，⼀个请求对象，服务端可以传回多个结果对象
// 典型的例⼦是客户端向服务端发送⼀个股票代码，服务端就把该股票的实时数据源源不断的返回给客户端
func (ser *GreeterServer) GetStream(request *proto.StreamRequestData, response proto.Greeter_GetStreamServer) error {
	fmt.Println(request.Data) // 打印了一下从客户端传入的数据
	var i = 0                 // 定义一个数字，就发送10次
	for {                     // 死循环源源不断向客户端发送
		// 以流的方式向客户端发送数据
		_ = response.Send(&proto.StreamResponseData{
			Data: fmt.Sprintf("当前服务器时间为：%v", time.Now().Unix()),
		})
		time.Sleep(time.Second) // 睡1s钟再发
		i++                     // 自增1
		if i == 10 {            // i为10的时候结束
			break
		}
	}
	return nil
}

// 客户端流模式，客户端传⼊多个请求对象，服务端返回⼀个响应结果，应用场景如：物联⽹终端向服务器报送数据
func (ser *GreeterServer) PutStream(request proto.Greeter_PutStreamServer) error {
	for {
		// 不断的接收并打印客户端发送过来的数据
		res, err := request.Recv()
		if err != nil {
			return err
		}
		fmt.Println(res.Data)
	}
}

// 双向流模式
func (ser *GreeterServer) AllStream(request proto.Greeter_AllStreamServer) error {
	// 开启两个协程，一个接收数据，一个发送数据
	var wg = sync.WaitGroup{}
	wg.Add(2)
	go func() { // 发送数据
		for {
			err := request.Send(&proto.StreamResponseData{
				Data: fmt.Sprintf("当前服务器时间为：%v", time.Now().Unix()),
			})
			if err != nil {
				fmt.Println(err)
				break
			}
			time.Sleep(time.Second) // 睡1s发送一次
		}
		wg.Done()
	}()

	go func() { // 不停接收数据
		for {
			res, err := request.Recv()
			if err != nil {
				fmt.Println(err)
				break
			}
			fmt.Println(res.Data)
		}
		wg.Done()
	}()

	wg.Wait()
	return nil
}
